package org.springframework.core.annotation;

import com.google.common.base.Preconditions;
import lombok.Getter;
import org.springframework.util.MethodKey;

import java.lang.annotation.Annotation;
import java.util.*;
import java.util.stream.Collectors;

@Getter
final class AnnotationAttributeMethodContext
        extends AbstractCollection<AnnotationAttributeMethod> {

    private final Annotation annotation;
    private final Class<? extends Annotation> annotationType;
    private final List<AnnotationAttributeMethod> annotationAttributeMethods;
    private final Map<MethodKey, AnnotationAttributeMethod> annotationAttributeMethodMap = new HashMap<>();

    public AnnotationAttributeMethodContext(Annotation annotation,
                                            List<AnnotationAttributeMethod> annotationAttributeMethods) {
        this.annotation = annotation;
        this.annotationType = annotation.annotationType();
        this.annotationAttributeMethods = annotationAttributeMethods;

        for (AnnotationAttributeMethod annotationAttributeMethod : annotationAttributeMethods) {
            annotationAttributeMethodMap.put(MethodKey.of(annotationAttributeMethod.getMethod()), annotationAttributeMethod);
        }
    }

    static AnnotationAttributeMethodContext of(Annotation annotation) {
        Preconditions.checkNotNull(annotation);

        Class<? extends Annotation> annotationType = annotation.annotationType();
        List<AnnotationAttributeMethod> annotationAttributeMethods = Arrays.stream(annotationType.getDeclaredMethods()).map(method -> AnnotationAttributeMethod.of(annotation, method)).collect(Collectors.toList());
        return new AnnotationAttributeMethodContext(annotation, annotationAttributeMethods);
    }

    @Override
    public Iterator<AnnotationAttributeMethod> iterator() {
        return new Iterator<AnnotationAttributeMethod>() {

            private int idx;

            @Override
            public boolean hasNext() {
                return idx < size();
            }

            @Override
            public AnnotationAttributeMethod next() {
                return annotationAttributeMethods.get(idx++);
            }
        };
    }

    @Override
    public int size() {
        return annotationAttributeMethods.size();
    }
}
